/*
 * Copyright (c) 2023 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <gtest/gtest.h>

#include <securec.h>
#include <vector>

#include "channel_operations_mock.h"
#include "sec_storage_core.h"
#include "test_helpers.h"

namespace OHOS {
namespace SeBaseServices {
namespace UnitTest {
using namespace testing;
TEST(SecStorageCoreTest, StorageSetFactoryResetAuthenticationKeyCaseSuccess)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80010201" // apdu header
                      "4100"     // 65 zeros
                      "00000000000000000000000000000000"
                      "00000000000000000000000000000000"
                      "00000000000000000000000000000000"
                      "00000000000000000000000000000000"
                      "00"; // expect le = 00
        EXPECT_EQ(input, expect);
        // 9000
        TestHelpers::StringFillUp("9000", response, responseLen);
        return SUCCESS;
    };

    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    uint8_t keyData[65] = {0};
    StorageAuthKey key = {.keyData = keyData, .keySize = sizeof(keyData)};
    auto ret = StorageSetFactoryResetAuthenticationKey(&channel, LEVEL_ALL_WIPE, ALGO_SM2, &key);
    EXPECT_EQ(ret, SUCCESS);
}

TEST(SecStorageCoreTest, StorageGetFactoryResetAuthenticationAlgoSuccess)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80020200" // apdu header
                      "00";      // expect le = 00
        EXPECT_EQ(input, expect);
        // 9000
        TestHelpers::StringFillUp("ab9000", response, responseLen);
        return SUCCESS;
    };

    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    FactoryResetAuthAlgo algo = ALGO_NIST_P256;

    auto ret = StorageGetFactoryResetAuthenticationAlgo(&channel, LEVEL_ALL_WIPE, &algo);
    EXPECT_EQ(ret, SUCCESS);
    EXPECT_EQ(algo, static_cast<FactoryResetAuthAlgo>(0xab));
}

TEST(SecStorageCoreTest, StoragePrepareFactoryResetSuccess)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80030000" // apdu header
                      "00";      // expect le = 00
        EXPECT_EQ(input, expect);
        std::string rsp = "0101010101010101010101010101010101010101010101010101010101010101" // chip id
                          "ABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB" // challenge
                          "9000";

        TestHelpers::StringFillUp(rsp, response, responseLen);
        return SUCCESS;
    };

    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    uint8_t nonce[256] = {0};
    uint32_t length = sizeof(nonce);

    auto ret = StoragePrepareFactoryReset(&channel, nonce, &length);
    EXPECT_EQ(ret, SUCCESS);
    EXPECT_EQ(length, 0x40);
    std::string expect = "0101010101010101010101010101010101010101010101010101010101010101"  // chip id
                         "ABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB"; // challenge
    EXPECT_EQ(TestHelpers::VectorToHexString(nonce, length), expect);
}

TEST(SecStorageCoreTest, StorageProcessFactoryResetSuccess)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80040200"                         // apdu header
                      "10"                               // lc
                      "0102030405060708090A0B0C0D0E0F10" // nonce
                      "00";                              // expect le = 00
        EXPECT_EQ(input, expect);

        TestHelpers::StringFillUp("9000", response, responseLen);
        return SUCCESS;
    };
    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    uint8_t nonce[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
    uint32_t length = sizeof(nonce);

    auto ret = StorageProcessFactoryReset(&channel, LEVEL_ALL_WIPE, nonce, length);
    EXPECT_EQ(ret, SUCCESS);
}

TEST(SecStorageCoreTest, StorageSetToUserModeSuccessCaseAllEnable)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80050000" // apdu header
                      "00";      // expect le = 00
        EXPECT_EQ(input, expect);

        TestHelpers::StringFillUp("9000", response, responseLen);
        return SUCCESS;
    };
    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};
    StorageUserModeConf config = {
        .pkResetable = 1,
        .slotsResetable = 1,
    };
    auto ret = StorageSetToUserMode(&channel, &config);
    EXPECT_EQ(ret, SUCCESS);
}

TEST(SecStorageCoreTest, StorageSetToUserModeSuccessCaseOnlyPkEnable)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80050002" // apdu header
                      "00";      // expect le = 00
        EXPECT_EQ(input, expect);

        TestHelpers::StringFillUp("9000", response, responseLen);
        return SUCCESS;
    };
    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};
    StorageUserModeConf config = {
        .pkResetable = 1,
        .slotsResetable = 0,
    };
    auto ret = StorageSetToUserMode(&channel, &config);
    EXPECT_EQ(ret, SUCCESS);
}

TEST(SecStorageCoreTest, StorageSetToUserModeSuccessCaseOnlySlotEnable)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80050001" // apdu header
                      "00";      // expect le = 00
        EXPECT_EQ(input, expect);

        TestHelpers::StringFillUp("9000", response, responseLen);
        return SUCCESS;
    };
    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};
    StorageUserModeConf config = {
        .pkResetable = 0,
        .slotsResetable = 1,
    };
    auto ret = StorageSetToUserMode(&channel, &config);
    EXPECT_EQ(ret, SUCCESS);
}

TEST(SecStorageCoreTest, StorageSetToUserModeSuccessCaseAllDisable)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80050003" // apdu header
                      "00";      // expect le = 00
        EXPECT_EQ(input, expect);

        TestHelpers::StringFillUp("9000", response, responseLen);
        return SUCCESS;
    };
    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};
    StorageUserModeConf config = {
        .pkResetable = 0,
        .slotsResetable = 0,
    };
    auto ret = StorageSetToUserMode(&channel, &config);
    EXPECT_EQ(ret, SUCCESS);
}

TEST(SecStorageCoreTest, StorageIsSlotOperateAlgorithmSupportedSuccessCaseSupportSm3AndSh256AndRawKey)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80060000" // apdu header
                      "00";      // expect le = 00
        EXPECT_EQ(input, expect);

        TestHelpers::StringFillUp("00039000", response, responseLen);
        return SUCCESS;
    };
    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(3)).WillRepeatedly(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    {
        uint32_t available = 0;
        auto ret = StorageIsSlotOperateAlgorithmSupported(&channel, ALGO_RAW_KEY, &available);
        EXPECT_EQ(ret, SUCCESS);
        EXPECT_EQ(available, 1);
    }
    {
        uint32_t available = 0;
        auto ret = StorageIsSlotOperateAlgorithmSupported(&channel, ALGO_HKDF_SHA256, &available);
        EXPECT_EQ(ret, SUCCESS);
        EXPECT_EQ(available, 1);
    }
    {
        uint32_t available = 0;
        auto ret = StorageIsSlotOperateAlgorithmSupported(&channel, ALGO_HKDF_SM3, &available);
        EXPECT_EQ(ret, SUCCESS);
        EXPECT_EQ(available, 1);
    }
}

TEST(SecStorageCoreTest, StorageIsSlotOperateAlgorithmSupportedSuccessCaseSupportSm3)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80060000" // apdu header
                      "00";      // expect le = 00
        EXPECT_EQ(input, expect);

        TestHelpers::StringFillUp("00029000", response, responseLen);
        return SUCCESS;
    };
    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(3)).WillRepeatedly(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    {
        uint32_t available = 0;
        auto ret = StorageIsSlotOperateAlgorithmSupported(&channel, ALGO_RAW_KEY, &available);
        EXPECT_EQ(ret, SUCCESS);
        EXPECT_EQ(available, 1);
    }
    {
        uint32_t available = 0;
        auto ret = StorageIsSlotOperateAlgorithmSupported(&channel, ALGO_HKDF_SHA256, &available);
        EXPECT_EQ(ret, SUCCESS);
        EXPECT_EQ(available, 0);
    }
    {
        uint32_t available = 0;
        auto ret = StorageIsSlotOperateAlgorithmSupported(&channel, ALGO_HKDF_SM3, &available);
        EXPECT_EQ(ret, SUCCESS);
        EXPECT_EQ(available, 1);
    }
}

TEST(SecStorageCoreTest, StorageIsSlotOperateAlgorithmSupportedSuccessCaseSupportSha256)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80060000" // apdu header
                      "00";      // expect le = 00
        EXPECT_EQ(input, expect);

        TestHelpers::StringFillUp("00019000", response, responseLen);
        return SUCCESS;
    };
    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(3)).WillRepeatedly(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    {
        uint32_t available = 0;
        auto ret = StorageIsSlotOperateAlgorithmSupported(&channel, ALGO_RAW_KEY, &available);
        EXPECT_EQ(ret, SUCCESS);
        EXPECT_EQ(available, 1);
    }
    {
        uint32_t available = 0;
        auto ret = StorageIsSlotOperateAlgorithmSupported(&channel, ALGO_HKDF_SHA256, &available);
        EXPECT_EQ(ret, SUCCESS);
        EXPECT_EQ(available, 1);
    }
    {
        uint32_t available = 0;
        auto ret = StorageIsSlotOperateAlgorithmSupported(&channel, ALGO_HKDF_SM3, &available);
        EXPECT_EQ(ret, SUCCESS);
        EXPECT_EQ(available, 0);
    }
}

TEST(SecStorageCoreTest, StorageIsFactoryResetAlgorithmSupportedSuccessCaseOnlyP256ButInputIsSm2)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80060000" // apdu header
                      "00";      // expect le = 00
        EXPECT_EQ(input, expect);
        // only support P256, RAWKEY
        TestHelpers::StringFillUp("01009000", response, responseLen);
        return SUCCESS;
    };
    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    uint32_t available = 0;
    auto ret = StorageIsFactoryResetAlgorithmSupported(&channel, ALGO_SM2, &available);
    EXPECT_EQ(ret, SUCCESS);
    EXPECT_EQ(available, 0);
}

TEST(SecStorageCoreTest, StorageIsFactoryResetAlgorithmSupportedSuccessCaseOnlyP256AndInputIsP256)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80060000" // apdu header
                      "00";      // expect le = 00
        EXPECT_EQ(input, expect);
        // only support P256, RAWKEY
        TestHelpers::StringFillUp("01009000", response, responseLen);
        return SUCCESS;
    };
    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    uint32_t available = 0;
    auto ret = StorageIsFactoryResetAlgorithmSupported(&channel, ALGO_NIST_P256, &available);
    EXPECT_EQ(ret, SUCCESS);
    EXPECT_EQ(available, 1);
}

TEST(SecStorageCoreTest, StorageIsFactoryResetAlgorithmSupportedSuccessCaseOnlySm2ButInputIsP256)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80060000" // apdu header
                      "00";      // expect le = 00
        EXPECT_EQ(input, expect);
        // only support SM2, RAWKEY
        TestHelpers::StringFillUp("02009000", response, responseLen);
        return SUCCESS;
    };
    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    uint32_t available = 0;
    auto ret = StorageIsFactoryResetAlgorithmSupported(&channel, ALGO_NIST_P256, &available);
    EXPECT_EQ(ret, SUCCESS);
    EXPECT_EQ(available, 0);
}

TEST(SecStorageCoreTest, StorageIsFactoryResetAlgorithmSupportedSuccessCaseOnlySm2AndInputIsSm2)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80060000" // apdu header
                      "00";      // expect le = 00
        EXPECT_EQ(input, expect);
        // only support SM2, RAWKEY
        TestHelpers::StringFillUp("02009000", response, responseLen);
        return SUCCESS;
    };
    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    uint32_t available = 0;
    auto ret = StorageIsFactoryResetAlgorithmSupported(&channel, ALGO_SM2, &available);
    EXPECT_EQ(ret, SUCCESS);
    EXPECT_EQ(available, 1);
}

TEST(SecStorageCoreTest, StorageSetAllSlotsSizeSuccess)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80070004" // apdu header
                      "08"       // lc = 4 * 2
                      "0400"     // 1024
                      "0040"     // 64
                      "1000"     // 4096
                      "2000"     // 8192
                      "00";      // expect le = 00
        EXPECT_EQ(input, expect);

        TestHelpers::StringFillUp("9000", response, responseLen);
        return SUCCESS;
    };
    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    uint16_t data[] = {1024, 64, 4096, 8192};
    auto ret = StorageSetAllSlotsSize(&channel, data, sizeof(data) / sizeof(uint16_t));
    EXPECT_EQ(ret, SUCCESS);
}

TEST(SecStorageCoreTest, StorageGetAllSlotsSizeSuccess)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80080000" // apdu header
                      "00";      // expect le = 00
        EXPECT_EQ(input, expect);

        std::string out = "0400" // 1024
                          "0040" // 64
                          "1000" // 4096
                          "2000" // 8192
                          "9000";

        TestHelpers::StringFillUp(out, response, responseLen);
        return SUCCESS;
    };
    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};
    uint16_t data[4] = {0};
    uint32_t size = 4;
    auto ret = StorageGetAllSlotsSize(&channel, data, &size);
    EXPECT_EQ(ret, SUCCESS);
    EXPECT_EQ(size, 4);
    EXPECT_EQ(data[0], 1024);
    EXPECT_EQ(data[1], 64);
    EXPECT_EQ(data[2], 4096);
    EXPECT_EQ(data[3], 8192);
}

TEST(SecStorageCoreTest, StorageAllocateSlotSuccessCaseRawKey)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80090064"                                                         // apdu header
                      "21"                                                               // lc = 0x21
                      "2F"                                                               // flag = 0x2f
                      "0102030405060000000000000000000000000000000000000000000000000000" // 32 bytes
                      "00";                                                              // expect le = 00
        EXPECT_EQ(input, expect);

        TestHelpers::StringFillUp("9000", response, responseLen);
        return SUCCESS;
    };
    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    StorageSlotAttr attr = {
        .algo = ALGO_RAW_KEY,
        .resetLevel = LEVEL_FACTORY_WIPE,
        .size = 128,
        .authOnRead = 1,
        .authOnWrite = 1,
        .authOnFree = 1,
    };
    uint8_t keyData[32] = {1, 2, 3, 4, 5, 6};
    StorageAuthKey key = {.keyData = keyData, .keySize = sizeof(keyData)};
    auto ret = StorageAllocateSlot(&channel, 100, &attr, &key);
    EXPECT_EQ(ret, SUCCESS);
}

TEST(SecStorageCoreTest, StorageAllocateSlotSuccessCaseSha256)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "80090064"                                                         // apdu header
                      "21"                                                               // lc = 0x21
                      "0F"                                                               // flag = 0x0f
                      "0102030405060000000000000000000000000000000000000000000000000000" // 32 bytes
                      "00";                                                              // expect le = 00
        EXPECT_EQ(input, expect);

        TestHelpers::StringFillUp("9000", response, responseLen);
        return SUCCESS;
    };
    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    StorageSlotAttr attr = {
        .algo = ALGO_HKDF_SHA256,
        .resetLevel = LEVEL_FACTORY_WIPE,
        .size = 128,
        .authOnRead = 1,
        .authOnWrite = 1,
        .authOnFree = 1,
    };
    uint8_t keyData[32] = {1, 2, 3, 4, 5, 6};
    StorageAuthKey key = {.keyData = keyData, .keySize = sizeof(keyData)};
    auto ret = StorageAllocateSlot(&channel, 100, &attr, &key);
    EXPECT_EQ(ret, SUCCESS);
}

TEST(SecStorageCoreTest, StorageGetSlotStatusSuccessCaseRawKey)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "800E0064" // apdu header
                      "00";      // expect le = 00
        EXPECT_EQ(input, expect);
        std::string out = "00000012" // readErrCnt = 0x12
                          "00000034" // writeErrCnt = 0x34
                          "00000056" // freeErrCnt = 0x56
                          "02"       // alloc = SLOT_ALLOCATE
                          "0078"     // size = 0x78
                          "2F"       // flag = 0x2f
                          "9000";
        TestHelpers::StringFillUp(out, response, responseLen);
        return SUCCESS;
    };
    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    StorageSlotStatus status;
    (void)memset_s(&status, sizeof(StorageSlotStatus), 0, sizeof(StorageSlotStatus));

    auto ret = StorageGetSlotStatus(&channel, 100, &status);
    EXPECT_EQ(ret, SUCCESS);
    EXPECT_EQ(status.readErrCnt, 0x12);
    EXPECT_EQ(status.writeErrCnt, 0x34);
    EXPECT_EQ(status.freeErrCnt, 0x56);
    EXPECT_EQ(status.status, SLOT_ALLOCATE);
    EXPECT_EQ(status.slotAttr.algo, ALGO_RAW_KEY);
    EXPECT_EQ(status.slotAttr.resetLevel, LEVEL_FACTORY_WIPE);
    EXPECT_EQ(status.slotAttr.authOnRead, 1);
    EXPECT_EQ(status.slotAttr.authOnWrite, 1);
    EXPECT_EQ(status.slotAttr.authOnFree, 1);
    EXPECT_EQ(status.slotAttr.size, 0x78);
}

TEST(SecStorageCoreTest, StorageFreeSlotSuccess)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "800A0064"                                                         // apdu header
                      "20"                                                               // lc = 0x20
                      "0102030405060000000000000000000000000000000000000000000000000000" // key
                      "00";                                                              // expect le = 00
        EXPECT_EQ(input, expect);

        TestHelpers::StringFillUp("9000", response, responseLen);
        return SUCCESS;
    };
    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    uint8_t keyData[32] = {1, 2, 3, 4, 5, 6};
    StorageAuthKey key = {.keyData = keyData, .keySize = sizeof(keyData)};

    auto ret = StorageFreeSlot(&channel, 100, &key);
    EXPECT_EQ(ret, SUCCESS);
}

TEST(SecStorageCoreTest, StorageWriteSlotSuccess)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "800C0064"                                                         // apdu header
                      "2A"                                                               // lc = 42 (32 + 2 + 2 + 6)
                      "0102030405060000000000000000000000000000000000000000000000000000" // key
                      "0010"                                                             // offset = 0x10
                      "0006"                                                             // data len = 6
                      "112233445566"                                                     // data
                      "00";                                                              // expect le = 00
        EXPECT_EQ(input, expect);

        TestHelpers::StringFillUp("9000", response, responseLen);
        return SUCCESS;
    };
    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    uint8_t keyData[32] = {1, 2, 3, 4, 5, 6};
    StorageAuthKey key = {.keyData = keyData, .keySize = sizeof(keyData)};
    StorageDataArea area = {.offset = 0x10, .length = 0x06};

    uint8_t bufferData[0x6] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
    StorageDataBuffer buffer = {.bufferData = bufferData, .bufferSize = sizeof(bufferData)};
    auto ret = StorageWriteSlot(&channel, 100, &key, &area, &buffer);
    EXPECT_EQ(ret, SUCCESS);
}

TEST(SecStorageCoreTest, StorageReadSlotSuccess)
{
    auto transmit = [](SecureElementContext *context, const uint8_t *command, uint32_t commandLen, uint8_t *response,
                        uint32_t *responseLen) -> ResultCode {
        (void)context;
        auto input = TestHelpers::VectorToHexString(command, commandLen);
        auto expect = "800B0064"                                                         // apdu header
                      "24"                                                               // lc = 0x24
                      "0102030405060000000000000000000000000000000000000000000000000000" // key
                      "0010"                                                             // offset = 0x10
                      "0006"                                                             // length len = 6
                      "00";                                                              // expect le = 00
        EXPECT_EQ(input, expect);

        TestHelpers::StringFillUp("0102030405069000", response, responseLen);
        return SUCCESS;
    };
    ChannelOperationsMock mock;
    EXPECT_CALL(mock, ChannelTransmit).Times(Exactly(1)).WillOnce(Invoke(transmit));
    CardChannel channel = {.context = nullptr, .oper = {.transmit = &ChannelOperationsMock::MockChannelTransmit}};

    uint8_t keyData[32] = {1, 2, 3, 4, 5, 6};
    StorageAuthKey key = {.keyData = keyData, .keySize = sizeof(keyData)};
    StorageDataArea area = {.offset = 0x10, .length = 0x06};

    uint8_t bufferData[128] = {0};
    StorageDataBuffer buffer = {.bufferData = bufferData, .bufferSize = sizeof(bufferData)};
    auto ret = StorageReadSlot(&channel, 100, &key, &area, &buffer);
    EXPECT_EQ(ret, SUCCESS);
    EXPECT_EQ(buffer.bufferSize, 6);
    EXPECT_EQ(TestHelpers::VectorToHexString(buffer.bufferData, buffer.bufferSize), "010203040506");
}
} // namespace UnitTest
} // namespace SeBaseServices
} // namespace OHOS